﻿namespace Hotel.Module.Management
{
    using System;
    using System.Collections.Generic;
    using ManagmentModels = Hotel.Module.Management.Models;
    using Entities = Hotel.Module.Management.DataRepository;
    using Hotel.Module.Infrastructure;
    using Hotel.Model.Infrastructure;
    using System.Linq;

    internal class ManagementDomainsRepository : IStorageController
    {
        public void SaveChanges()
        {
            EntityStorage.SaveChanges();
        }
        
        /// <summary>
        /// Adds new entity to the storage
        /// </summary>
        /// <param name="tableEntity">Entity</param>
        /// <exception cref="ArgumentNullException">Fires if entity is null</exception>
        /// <exception cref="InvalidOperationException">Fires if Entity was not initialized</exception>
        public void Add<T>(T tableEntity) where T : Model.Infrastructure.IDistributedStorageEntity
        {
            if (tableEntity is ManagmentModels.Order)
            {
                ManagmentModels.Order item = tableEntity as ManagmentModels.Order;
                Entities.Order result = new Entities.Order();
                item.AssignTo(result);
                EntityStorage.AddToOrders(result);
                return;
            }
            if (tableEntity is ManagmentModels.Assignment)
            {
                ManagmentModels.Assignment item = tableEntity as ManagmentModels.Assignment;
                Entities.Assignment result = new Entities.Assignment();
                item.AssignTo(result);
                EntityStorage.AddToAssignments(result);
                return;
            }
            throw new NotSupportedException();
        }

        /// <summary>
        /// Updates some entity
        /// </summary>
        /// <param name="tableEntity">Entity</param>
        /// <exception cref="ArgumentNullException">Fires if entity is null</exception>
        /// <exception cref="InvalidOperationException">Fires if Entity was not initialized</exception>
        public void Update<T>(T tableEntity) where T : Model.Infrastructure.IDistributedStorageEntity
        {
            if (tableEntity is ManagmentModels.Order)
            {
                ManagmentModels.Order item = tableEntity as ManagmentModels.Order;
                foreach (var entityOrder in EntityStorage.Orders)
                {
                    if (entityOrder.Id == item.ID)
                    {
                        item.AssignTo(entityOrder);
                        break;
                    }
                }
                return;
            }

            if (tableEntity is ManagmentModels.Assignment)
            {
                ManagmentModels.Assignment item = tableEntity as ManagmentModels.Assignment;
                foreach (var entityAssignment in EntityStorage.Assignments)
                {
                    if (entityAssignment.Id == item.ID)
                    {
                        item.AssignTo(entityAssignment);
                        break;
                    }
                }
                return;
            }
            throw new NotSupportedException();
        }

        /// <summary>
        /// Deletes entity
        /// </summary>
        /// <param name="tableEntity">Entity</param>
        /// <exception cref="ArgumentNullException">Fires if entity is null</exception>
        /// <exception cref="InvalidOperationException">Fires if Entity was not initialized</exception>
        public void Delete<T>(T tableEntity) where T : Model.Infrastructure.IDistributedStorageEntity
        {
            if (tableEntity is ManagmentModels.Order)
            {
                ManagmentModels.Order item = tableEntity as ManagmentModels.Order;

                Entities.Order result = null;
                foreach (var entityOrder in EntityStorage.Orders)
                {
                    if (entityOrder.Id == item.ID)
                    {
                        result = entityOrder;
                        break;
                    }
                }
                if (result != null)
                {
                    EntityStorage.DeleteObject(result);
                }
                return;
            }

            if (tableEntity is ManagmentModels.Assignment)
            {
                ManagmentModels.Assignment item = tableEntity as ManagmentModels.Assignment;

                Entities.Assignment result = null;
                foreach (var entityAssignment in EntityStorage.Assignments)
                {
                    if (entityAssignment.Id == item.ID)
                    {
                        result = entityAssignment;
                        break;
                    }
                }
                if (result != null)
                {
                    EntityStorage.DeleteObject(result);
                }
                return;
            }

            throw new NotSupportedException();
        }

        public T Find<T>(Predicate<T> match)
        {
            if (typeof(T) == typeof(Models.Assignment))
            {
                foreach (var item in EntityStorage.Assignments)
                {
                    object result = Models.Assignment.FromEnityModel(item);
                    if (match((T)result))
                        return (T)result;
                }

            }

            if (typeof(T) == typeof(Models.Order))
            {
                foreach (var item in EntityStorage.Orders)
                {
                    object result = Models.Order.FromEnityModel(item);
                    if (match((T)result))
                        return (T)result;
                }
            }

            return default(T);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IEnumerable<T> Enumerate<T>() where T : IDistributedStorageEntity
        {
            if (typeof(T) == typeof(Models.Assignment))
            {
                var collection = from item in EntityStorage.Assignments select item;
                foreach (var item in collection)
                {
                    object result = ManagmentModels.Assignment.FromEnityModel(item);
                    yield return (T)result;
                }
            }

            if (typeof(T) == typeof(Models.Order))
            {
                var collection = from item in EntityStorage.Orders select item;
                foreach (var item in collection)
                {
                    object result = ManagmentModels.Order.FromEnityModel(item);
                    yield return (T)result;
                }
            }          
        }

        public IQueryable<T> GetQuery<T>() where T : IDistributedStorageEntity
        {
            if (typeof(T) == typeof(Models.Assignment))
            {
                var collection = from item in EntityStorage.Assignments select item;
                List<Models.Assignment> TCollection = new List<Models.Assignment>();
                foreach (var item in collection)
                {                    
                    TCollection.Add(ManagmentModels.Assignment.FromEnityModel(item));
                }
                return (IQueryable<T>)TCollection.AsQueryable();
            }

            if (typeof(T) == typeof(Models.Order))
            {
                var collection = from item in EntityStorage.Orders select item;
                List<Models.Order> TCollection = new List<Models.Order>();
                foreach (var item in collection)
                {
                    TCollection.Add(ManagmentModels.Order.FromEnityModel(item));
                }
                return (IQueryable<T>)TCollection.AsQueryable();
            }

            return default(IQueryable<T>);
        }

        #region Disposing

        ~ManagementDomainsRepository()
        {
            Dispose(false);
        }

        private bool disposed = false;
        private void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    //Dispose managed resources
                }
                disposed = true;
            }
        }

        /// <summary>
        /// Disposing
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion

        private readonly Entities.ManagementEntityModelContainer EntityStorage = new Entities.ManagementEntityModelContainer();

    }
}